﻿using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RaytracerLib;
using RaytracerLib.MathLib;
using TomanuExtensions;
using System;
using RaytracerLib.MathLib.Polynomials;
using System.Diagnostics;

namespace RaytracerTest
{
    public class TestBase
    {
        private TestContext m_testContext;

        public TestContext TestContext
        {
            get
            {
                return m_testContext;
            }
            set
            {
                m_testContext = value;
            }
        }

        [DebuggerNonUserCode]
        public static void AreAlmostRelativeEquals(Polynomial a_expected, Polynomial a_actual,
            double a_precision = Constants.DOUBLE_PRECISION)
        {
            bool eq = a_expected.IsAlmostRelativeEquals(a_actual, a_precision);

            if (eq)
                return;

            Assert.Fail("Expected: {0}; Actual: {1}", a_expected, a_actual);
        }

        [DebuggerNonUserCode]
        public static void AreAlmostRelativeEquals(Vector2 a_expected, Vector2 a_actual,
            double a_precision = Constants.DOUBLE_PRECISION)
        {
            bool eq = a_expected.IsAlmostRelativeEquals(a_actual, a_precision);

            if (eq)
                return;

            Assert.Fail("Expected: {0}; Actual: {1}", a_expected, a_actual);
        }

        [DebuggerNonUserCode]
        public void AreAlmostRelativeEquals(Vector3 a_expected, Vector3 a_actual, 
            double a_precision = Constants.DOUBLE_PRECISION)
        {
            bool eq = a_expected.IsAlmostRelativeEquals(a_actual, a_precision);

            if (eq)
                return;

            Assert.Fail("Expected: {0}; Actual: {1}", a_expected, a_actual);
        }

        [DebuggerNonUserCode]
        public static void AreAlmostRelativeEquals(double a_expected, double a_actual,
            double a_precision = Constants.DOUBLE_PRECISION)
        {
            bool eq = a_expected.IsAlmostRelativeEquals(a_actual, a_precision);

            if (eq)
                return;

            Assert.Fail("Expected: {0}; Actual: {1}", a_expected, a_actual);
        }

        [DebuggerNonUserCode]
        public static void AreAlmostRelativeEquals(float a_expected, double a_actual,
            float a_precision = Constants.FLOAT_PRECISION)
        {
            bool eq = a_expected.IsAlmostRelativeEquals((float)a_actual, a_precision);

            if (eq)
                return;

            Assert.Fail("Expected: {0}; Actual: {1}", a_expected, a_actual);
        }

        [DebuggerNonUserCode]
        public static void AreAlmostRelativeEquals(float a_expected, float a_actual,
            float a_precision = Constants.FLOAT_PRECISION)
        {
            bool eq = a_expected.IsAlmostRelativeEquals(a_actual, a_precision);

            if (eq)
                return;

            Assert.Fail("Expected: {0}; Actual: {1}", a_expected, a_actual);
        }

        [DebuggerNonUserCode]
        public static void AreAlmostRelativeEquals(double a_expected, float a_actual,
            float a_precision = Constants.FLOAT_PRECISION)
        {
            bool eq = ((float)a_expected).IsAlmostRelativeEquals(a_actual, a_precision);

            if (eq)
                return;

            Assert.Fail("Expected: {0}; Actual: {1}", a_expected, a_actual);
        }

        [DebuggerNonUserCode]
        public static void AreAlmostRelativeEquals(Matrix3 a_expected, Matrix3 a_actual,
            double a_precision = Constants.DOUBLE_PRECISION)
        {
            bool eq = a_expected.IsAlmostRelativeEquals(a_actual, a_precision);

            if (eq)
                return;

            Assert.Fail("Expected: {0}; Actual: {1}", a_expected, a_actual);
        }

        [DebuggerNonUserCode]
        public static void AreAlmostRelativeEquals(Matrix4 a_expected, Matrix4 a_actual,
            double a_precision = Constants.DOUBLE_PRECISION)
        {
            bool eq = a_expected.IsAlmostRelativeEquals(a_actual, a_precision);

            if (eq)
                return;

            Assert.Fail("Expected: {0}; Actual: {1}", a_expected, a_actual);
        }

        [DebuggerNonUserCode]
        public static void AreAlmostRelativeEquals(Microsoft.DirectX.Vector4 a_expected,
            Vector3 a_actual)
        {
            var expected = new Vector3(a_expected.X, a_expected.Y, a_expected.Z);
            expected.IsAlmostRelativeEquals(a_actual, Constants.D3D_TEST_PRECISION);
        }

        [DebuggerNonUserCode]
        public static void AreAlmostRelativeEquals(Microsoft.DirectX.Vector3 a_expected,
            Vector3 a_actual)
        {
            var expected = new Vector3(a_expected.X, a_expected.Y, a_expected.Z);
            expected.IsAlmostRelativeEquals(a_actual, Constants.D3D_TEST_PRECISION);
        }

        [DebuggerNonUserCode]
        public static void AreAlmostRelativeEquals(Microsoft.DirectX.Matrix a_expected,
            Matrix3 a_actual)
        {
            Matrix3 expected = new Matrix3(
                new double[]
                {
                    a_expected.M11, a_expected.M12, a_expected.M13,
                    a_expected.M21, a_expected.M22, a_expected.M23,
                    a_expected.M31, a_expected.M32, a_expected.M33
                }
            );

            AreAlmostRelativeEquals(expected, a_actual, Constants.D3D_TEST_PRECISION);
        }

        [DebuggerNonUserCode]
        public static void AreAlmostRelativeEquals(Microsoft.DirectX.Matrix a_expected,
            Matrix4 a_actual)
        {
            Matrix4 expected = new Matrix4(
                new double[]
                {
                    a_expected.M11, a_expected.M12, a_expected.M13, a_expected.M14,
                    a_expected.M21, a_expected.M22, a_expected.M23, a_expected.M24,
                    a_expected.M31, a_expected.M32, a_expected.M33, a_expected.M34,
                    a_expected.M41, a_expected.M42, a_expected.M43, a_expected.M44
                }
            );

            AreAlmostRelativeEquals(expected, a_actual, Constants.D3D_TEST_PRECISION);
        }

        public static bool IncCounter(int[] a_ar, int a_size, int a_base)
        {

            for (int i = 0; i < a_size; i++)
            {
                int x = a_ar[i];
                x++;
                if (x == a_base)
                {
                    a_ar[i] = 0;
                    continue;
                }
                else
                {
                    a_ar[i] = x;
                    return true;
                }
            }

            return false;
        }
    }
}